import cv2

class PyCVParser():
    '''利用opencv获取图片表格区域'''

    def line_segement(self,binroi):
        rbinroi = cv2.bitwise_not(binroi)  # 黑底白景
        height = int(binroi.shape[0]*1.0/800+1)
        width = int(binroi.shape[1]*1.0 /10 + 1)
        rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (width, height))
        # rect_kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 10))
        rect_dilate = cv2.dilate(rbinroi, rect_kernel)
        # cv2.namedWindow("Image")
        # cv2.imshow("Image", rect_dilate)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()
        contours, hierarchy = cv2.findContours(rect_dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
        temp = []
        for i in range(len(contours)):
            x,y,w,h = cv2.boundingRect(contours[i])
            temp.append([x,y,w,h])
        return temp

    def haveConnectedROI(self,binroi):
        rects = self.line_segement(binroi)
        tl_x = binroi.shape[1]
        tl_y = binroi.shape[0]
        br_x = 0
        br_y = 0
        r = False
        for i in range(len(rects)):
            # partrect = rbinroi[rects[i][0]: rects[i][0]+rects[i][2],rects[i][1]:rects[i][1]+rects[i][3]]
            if (rects[i][3] > 80):
                tl_x = rects[i][0] if rects[i][0] < tl_x else tl_x
                tl_y = rects[i][1] if rects[i][1] < tl_y else tl_y
                br_x = rects[i][0] + rects[i][2] if rects[i][0] + rects[i][2] > br_x else br_x;
                br_y = rects[i][1] + rects[i][3] if rects[i][1] + rects[i][3] > br_y else br_y;
                # flag = 1;
        if br_x != 0 and br_y != 0 and br_x > tl_x and br_y > tl_y:
            r = True

        return r,tl_x,tl_y,br_x,br_y

    def parse_table(self,binroi,srcimg):
        rbinroi = cv2.bitwise_not(binroi) #黑底白景
        scale=20
        horizontalsize = binroi.shape[1] * 1.0 / scale + 1
        horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontalsize, 1))
        hor_erode = cv2.erode(rbinroi, horizontalStructure, (-1, -1));
        hor_dilate = cv2.dilate(hor_erode, horizontalStructure, (-1, -1));
        binary,contours, hierarchy = cv2.findContours(hor_dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE,(0, 0))
        tablepoint = []
        table_pos = None
        width ,height = binroi.shape[1],binroi.shape[0]
        for i in range(len(contours)):
            if (contours[i].back().x-contours[i][0].x > 100):
                lines = [contours[i][0].x,contours[i][0].y,contours[i][-1].x,contours[i][-1].y]
                tablepoint.append(lines)
        if len(tablepoint) != 0:
            res,tl_x,tl_y,br_x,br_y = self.haveConnectedROI(binroi.copy())
            if res:
                r_x = (tl_x - 20) * 1.0 / width
                r_y = (tl_y - 80) * 1.0 / height
                r_z = (br_x + 20) * 1.0 / width
                r_w = (br_y + 80) * 1.0 / height
                table_pos = [0, r_x, r_y, r_z, r_w]
                srcimg[tl_x:br_x, tl_y:br_y] = 255
            else:
                start_x = end_x = tablepoint[- 1][0]
                start_y = end_y = tablepoint[- 1][1]
                flag2 ,flag3 = 0,0
                rects = self.line_segement(binroi)
                for j in range(len(rects)):
                    rbinrect = rbinroi(rects[j][0],rects[j][1],rects[j][2],rects[j][3])
                    height1 = binroi.shape[0]*1.0
                    width1 = binroi.shape[1]*1.0/50+1
                    rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (width1, height1));
                    rect_kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT,(width1, height1));
                    rbin_dilate = cv2.dilate(rbinrect, rect_kernel);
                    rbin_erode = cv2.erode(rbin_dilate, rect_kernel2);
                    contours2, hierarchy = cv2.findContours(rbin_erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
                    if len(contours2) >= 2:
                        if j==0:
                            flag3=1
                        if j==len(rects)-1:
                            flag3=2
                        if rects[j][1] < start_y:
                            start_y = rects[j][1]
                            flag2 = 1
                        if rects[j][1]+rects[j][3] > end_y:
                            end_y = rects[j][1]+rects[j][3]
                            break
                    else:
                        if flag2==0 and rects[j][1]+rects[j][3]+5<start_y:
                            break
                if end_y-start_y != 0:
                    r_x = (start_x - 10) * 1.0 / binroi.shape[1];
                    r_y = (start_y - 10) * 1.0 / binroi.shape[0];
                    r_z = (tablepoint[-1][2] + 10) * 1.0 / binroi.shape[1];
                    r_w = (end_y + 10) * 1.0 / binroi.shape[0];
                    table_pos = [flag3,r_x,r_y,r_z,r_w]
                    srcimg[r_x:r_z,r_y:r_w] = 255
        return table_pos

    def parse_image(self, binroi,cvimg):
        res, tl_x, tl_y, br_x, br_y = self.haveConnectedROI(binroi.copy())
        img_pos = None
        if res:
            cvimg[tl_x:br_x,tl_y:br_y] = 255
            img_pos = [tl_x, tl_y, br_x, br_y]
        return img_pos

    def layout_mode(self,binsrc):
        dl2 = binsrc.shape[1] / 2
        dl3 = binsrc.shape[1]  / 3
        mode = 1
        rbinsrc = cv2.bitwise_not(binsrc)  # 黑底白景
        rect_kernel3 = cv2.getStructuringElement(cv2.MORPH_RECT, (int(binsrc.shape[1] / 60 + 1), int(binsrc.shape[0] / 60 + 1)))
        rect_kernel4 = cv2.getStructuringElement(cv2.MORPH_RECT, (int(binsrc.shape[1] / 100 + 1), 1))
        rbinsrc_dilate = cv2.dilate(rbinsrc, rect_kernel3)
        rbinsrc_erode = cv2.erode(rbinsrc_dilate, rect_kernel4)
        contours, hierarchy = cv2.findContours(rbinsrc_erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
        for i in range(len(contours)):
            x,y,w,h = cv2.boundingRect(contours[i])
            # print(binsrc.shape[0],binsrc.shape[1])
            end_x = x+w
            if (end_x > dl3 * 5 / 2 and h > 100  and  w > dl3 * 2 / 3 and w < dl3):
                mode = 3
                break
            if (end_x > dl2 * 3 / 2 and h > 100 and w > dl2 * 2 / 3 and w < dl2):
                mode = 2
                break
        return mode

    def segment_rois(self,mode,binsrc):
        roilist = []
        rbinsrc = cv2.bitwise_not(binsrc)  # 黑底白景
        if mode ==1:
            height = int(binsrc.shape[0] * 1.0 / 20 + 1)
            width = int(binsrc.shape[1] * 1.0)
            rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (width, height))
        else:
            height = int(binsrc.shape[0] * 1.0 / 50 + 1)
            width = int(binsrc.shape[1] * 1.0 / 60 + 1)
            rect_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (width, height))

        rbinsrc_dilate = cv2.dilate(rbinsrc, rect_kernel)
        contours, hierarchy = cv2.findContours(rbinsrc_dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
        for i in range(len(contours)):
            x, y, w, h = cv2.boundingRect(contours[i])
            roilist.append([x, y, w, h])
        return roilist

